﻿using System;
using System.Web.UI;
using BigfootMVC.Helpers;

namespace BigfootMVC.DNN
{

    /// <summary>
    /// This is the base class of the RouteUserControl. In a purely MVC application it is the only registered DNN 
    /// control and handles all the MVC requests for the module. It uses the URL route parameter to identify the proper
    /// controller and action to execute
    /// </summary>
    public abstract class BaseRouteUserControl : DotNetNuke.Entities.Modules.PortalModuleBase
    {

        /// <summary>
        /// This funciton must be overridden by the inheritor in order to Init the MVC application object
        /// </summary>
        public abstract DnnApp InitApp();

        /// <summary>
        /// Called inmediately after the route has been created and before the request has been processed
        /// </summary>
        public abstract void RouteCreated(RouteInfo Route);

        /// <summary>
        /// Holds the current route information
        /// </summary>
        public RouteInfo Route;

        /// <summary>
        /// Holds a reference to the application class created for this instance of the module
        /// </summary>
        public DnnApp App;

        // Initialize the route control
        protected void Page_Init(object sender, EventArgs e)
        {
            // Init the MVC app
            App = InitApp();

            try
            {
                // Get the current route request
                var paramName = Params.QS.Route(ModuleId);
                var routeData = App.Values.GetValue(paramName);
                Route = string.IsNullOrEmpty(routeData)
                                ? new RouteInfo("Home", "Index", this, PortalId, App)
                                : App.DecodeUrlRoute(routeData, this);
                Route.User = UserInfo;
                Route.App = App;

                // Call the route created
                RouteCreated(Route);

                // Load the validation strings
                App.SetupLocalResources();

                // Execute the action
                var result = RouteHelper.ExecuteAction(Route);
                
                // Process the result
                ProcessResult(result);
            }
            catch (Exception ex)
            {
                App.HandleException(ex, false);
                LoadErrorView(ex);
            }

        }

        private Control GetRouteContent()
        {
            return FindControl("RouteContent");
        }

        private void ProcessResult(ActionResult result)
        {
            switch (result.Type)
            {
                case ActionResult.ActionTypeEnum.View:
                    var contentHolder = GetRouteContent();
                    contentHolder.Controls.Add(DnnApp.LoadView(result.Route.ViewPath, result.Data, this.Page, "Route", result.Route));
                    break;

                case ActionResult.ActionTypeEnum.Literal:
                    result.Route.App.RenderLiteral(result.Data.ToString());
                    break;

                case ActionResult.ActionTypeEnum.Json:
                    result.Route.App.RenderJson(result.Data.ToString());
                    break;
            }
        }

        private void LoadErrorView(Exception ex)
        {
            // Load the error view
            try
            {
                var returnUrl = "";
                if (Route != null) returnUrl = Route.GetMvcUrl();
                var data = ErrorViewModel.Create(ex, returnUrl);
                GetRouteContent().Controls.Add(DnnApp.LoadView(App.ErrorViewPath, data, this.Page, "Route", Route));
            }
            catch (Exception)
            {
                Response.Write(ex.ToString());
            }
            
        }

        
        /// <summary>
        /// Gets the form name. Can be used by jquery (includes the pre #)
        /// </summary>
        public string FormName() { return Page.Form != null ? "#" + Page.Form.ClientID : "#Form"; }


        /// <summary>
        /// Inclues all view helper functions (i.e. RenderPartial, E, UrlP, Url, Html, JS, TB, Ajax, CreatePartialForm, SubmitPartialForm, RenderIf, Post values, etc.)
        /// </summary>
        public DnnViewHelper BF
        {
            get { return _viewHelper ?? (_viewHelper = new DnnViewHelper(Route, false)); }
        }
        private DnnViewHelper _viewHelper;

        // These are alias functions from BF used for convinience
        public string uid(string name) { return BF.uid(name); }
        public HtmlHelper Html { get { return BF.Html; } }
        public JSHelper JS { get { return BF.JS; } }
        public TagBuilder TB(string tagName) { return BF.TB(tagName); }
        public string E(string value) { return BF.E(value); }
        public string F(string format, params string[] values) { return BF.F(format, values); }
        public AjaxRequest Ajax(string url) { return BF.Ajax(url); }
        public UrlHelper Url { get { return BF.Url; } }
        public string UrlP(string paramName, string value) { return BF.UrlP(paramName, value); }
        public string UrlP(string paramName, int value) { return BF.UrlP(paramName, value); }
    }


}
